﻿#include "customtablemodel.h"

CustomTableModel::CustomTableModel(QObject *parent) :
    QAbstractTableModel(parent)
{

     rowCheckStateMap.clear();
}

int CustomTableModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent)
    return m_nRowCount;
}

int CustomTableModel::columnCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent)
    return m_nColCount;
}

QVariant CustomTableModel::data(const QModelIndex &index, int role) const
{
    int row = index.row();
    int col = index.column();
    if (index.isValid() == false ||
        row < 0 || row >= m_nRowCount ||
        col < 0 || col >= m_nColCount)
    {
        return QVariant();
    }

    if (role == Qt::TextAlignmentRole)
    {
        return int(Qt::AlignLeft | Qt::AlignVCenter);
    }
    else if (role == Qt::DisplayRole || role == Qt::ToolTipRole || role == Qt::EditRole)
    {
        if(row >= m_v2d_data.size() || col >= m_v2d_data[row].size())
            return QVariant();
        return m_v2d_data[row][col];
    }
//    else if (role == Qt::StatusTipRole)
//    {
//        QString header = m_vec_header.value(col);
//        if (header.isEmpty())
//        {
//            return m_v2d_data[row][col];
//        }
//        else
//        {
//            return header + QStringLiteral(":") + m_v2d_data[row][col];
//        }
//    }
    if (role == Qt::CheckStateRole)
        {
            if (index.column() == colNumberWithCheckBox)
            {
                if (rowCheckStateMap.contains(index.row()))
                return rowCheckStateMap[index.row()] == Qt::Checked ? Qt::Checked : Qt::Unchecked; return Qt::Unchecked;
            }
        }

    return QVariant();
}

bool CustomTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    int row = index.row();
    int col = index.column();
    if (index.isValid() == false ||
        row < 0 || row >= m_nRowCount ||
        col < 0 || col >= m_nColCount)
    {
        return false;
    }

    int orow = orginalIndex(row);
    if (role == Qt::EditRole &&
        orow != -1)
    {
        m_vec_rowModified[orow] = true;
        m_v2d_data[row][col] = value.toString();
        emit dataChanged(index, index);
        return true;
    }
    else if (role == Qt::CheckStateRole && index.column() == colNumberWithCheckBox)
    {
        if (value == Qt::Checked) //
        {
            rowCheckStateMap[index.row()] = Qt::Checked;
            return true;
        }
        else
        {
            rowCheckStateMap[index.row()] = Qt::Unchecked;
            return true;
        }
    }
    else
    {
        return QAbstractTableModel::setData(index, value, role);
    }
}

QVariant CustomTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (role == Qt::DisplayRole)
    {
        if (orientation == Qt::Horizontal)
        {
            return m_vec_header.value(section);
        }
        else
        {
            return section + 1;
        }
    }

    return QAbstractTableModel::headerData(section, orientation, role);
}

void CustomTableModel::sort(int column, Qt::SortOrder order)
{
    if (column >= m_nColCount ||
        column < 0)
    {
        return;
    }

    if (m_bSettingModelData == false)
    {
        beginResetModel();
    }

    std::sort(m_v2d_data.begin(), m_v2d_data.end(), [order, column](const QVector<QString> &a, const QVector<QString> &b)
    {
        if (order == Qt::AscendingOrder)
        {
            return a[column] < b[column];
        }
        else
        {
            return a[column] > b[column];
        }
    });

    m_hash_originalToCurrent.clear();
    for (int row = 0; row < m_nRowCount; ++row)
    {
        m_hash_originalToCurrent[orginalIndex(row)] = row;
    }

    m_nSortedColumn = column;
    m_orderSorted = order;
    if (m_bSettingModelData == false)
    {
        endResetModel();
    }
}

int CustomTableModel::orginalIndex(int row) const
{
    if (row < 0 || row >= m_nRowCount)
    {
        return -1;
    }
    else
    {
        return m_v2d_data[row][m_nColCount].toInt();
    }
}

void CustomTableModel::setHeaders(const QList<QString> &headers)
{
    if (m_bUseReset)
    {
        beginResetModel();
    }

    m_vec_header = headers.toVector();
    m_nColCount = m_vec_header.size();

    if (m_bUseReset)
    {
        endResetModel();
    }
}

void CustomTableModel::setHeadersAndData(const QList<QString> &headers,
                                         const QVector<QVector<QString> > &data)
{
    m_bUseReset = false;
    beginResetModel();
    setHeaders(headers);
    setModelData(data);
    endResetModel();
    m_bUseReset = true;
}

bool CustomTableModel::isRowModified(int originalRow) const
{
    if (originalRow < 0 || originalRow >= m_nRowCount)
    {
        return false;
    }
    else
    {
        return m_vec_rowModified[originalRow];
    }
}

QVector<QString> CustomTableModel::modelLine(int originalRow) const
{
    if (originalRow < 0 || originalRow >= m_nRowCount || m_hash_originalToCurrent.contains(originalRow) == false)
    {
        return QVector<QString>();
    }
    else
    {
        return m_v2d_data[m_hash_originalToCurrent[originalRow]];
    }
}

QVector<QString> CustomTableModel::headers() const
{
    return m_vec_header;
}

QVector<QVector<QString> > CustomTableModel::modelData() const
{
    return m_v2d_data;
}
Qt::ItemFlags CustomTableModel::flags( const QModelIndex &index ) const
{
    if
    (!index.isValid())
    return 0;

    if (index.column() == colNumberWithCheckBox)
       return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable;

    return  Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}
void CustomTableModel::setModelData(const QVector<QVector<QString> > &data)
{
    m_bSettingModelData = true;
    if (m_bUseReset)
    {
        beginResetModel();
    }

    m_v2d_data = data;
    m_nRowCount = m_v2d_data.size();
    m_vec_rowModified.clear();
    for (int i = 0; i < m_nRowCount; ++i)
    {
        if(m_nColCount < m_v2d_data[i].size())
        {
            m_v2d_data[i][m_nColCount] = QString::number(i);
        }
        else
        {
            m_v2d_data[i].append(QString::number(i));
        }
        m_vec_rowModified << false;
    }

    sort(m_nSortedColumn, m_orderSorted);

    if (m_bUseReset)
    {
        endResetModel();
    }

    m_bSettingModelData = false;
}
void CustomTableModel::setCheckcolumn(const int& ncolumn)
{
    colNumberWithCheckBox = ncolumn;
}
